/**
 * 递归判断
 */
// 数组包含
type IsEqual<A,B> = (A extends B ? true : false) & (B extends A ? true : false);
type IsEqualT = IsEqual<'1',''>
type ArrayIncludes<Arr extends unknown[],Ele extends unknown> =
  Arr extends [infer First,...infer Rest] ?
  (IsEqual<First,Ele> extends true ?
    true :
    ArrayIncludes<Rest,Ele>) :
  false;
type IsArrayIncludes = ArrayIncludes<[1,2,3,4],4> // true
// 去重
type ArrayUnique<Arr extends unknown[],Res extends unknown[] = []> =
  Arr extends [infer First,...infer Rest] ?
  ArrayIncludes<Res,First> extends false ?
  ArrayUnique<Rest,[...Res,First]>
  : ArrayUnique<Rest,Res>
  : Res;
type TestArrayUnique = ArrayUnique<[2,3,2,1]>; // [2,3,1]
// 递归创建重复
type ArrayCreate<Len extends number,Ele extends unknown = unknown,Res extends unknown[] = []> =
  Res['length'] extends Len ?
  Res :
  ArrayCreate<Len,Ele,[...Res,Ele]>;
type TestArrayCreate = ArrayCreate<15,10>; // [10, 10, 10, 10, 10]


type CamelCaseAll<Str extends string> =
  Str extends `${infer Left}_${infer Right}${infer Rest}` ?
  `${Left}${GetUppercase<Right>}${CamelCase<Rest>}` : Str;

type TestCamelCase2 = CamelCaseAll<'is_need_update'>; // isNeedUpdate

type ReplaceAll<Str extends string,From extends string,To extends string> =
  Str extends `${infer Prefix}${From}${infer Subfix}` ?
  `${Prefix}${To}${ReplaceAll<Subfix,From,To>}`
  : Str;
type TestReplaceAll = ReplaceAll<'hello world world','world','hello'>; // 'hello hello hello'

type Person1 = {
  name: string
  age: number
  job: string
  address: {
    province: string
    city: string
    district: string
  }
}
type DeepReadonly<T extends object> =
  T extends any ?
  {
    readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
  }
  : never
type RPerson = DeepReadonly<Person1>

// 加减乘除
type TAdd<A extends number,B extends number> = [...ArrayCreate<A>,...ArrayCreate<B>]['length'];
type TAdd1 = TAdd<1,2>

type Subtract<A extends number,B extends number> = ArrayCreate<A> extends [...arr1: ArrayCreate<B>,...arr2: infer Rest] ? Rest['length'] : never
type TSubtract = Subtract<5,3>

type Multiply<A extends number,B extends number,Pre extends unknown[] = []> = B extends 0 ? Pre['length'] : Multiply<A,Subtract<B,1>,[...ArrayCreate<A,number>,...Pre]>;
type TMultiply = Multiply<2,3>

type Divide<A extends number,B extends number,Pre extends unknown[] = []> = A extends 0 ? Pre['length'] : Divide<Subtract<A,B>,B,[unknown,...Pre]>;
type TDivide = Divide<4,2>